unit uCxtDALVDCenter;

interface

uses
  SysUtils, Classes, Windows, SyncObjs, DLDatObj, uDZSysUtils, uDZWinsock2,
  uDZPersistent, uDZThread, uDZSocket, uDZSocketUtils,
  uGxtTypes, uGxtSvcIntf, uCxtTypes, uCxtDAL, uCxtConst, uViDef, uTcpDef,
  uAppConfig, uCxtPackage;

type
  TVDClientSocket = class(TDzCustomClientSocket)
  
  end;

  TVDConnection = class
  public
    Socket: TDzClientSocket;
    Next: TVDConnection;
    constructor Create;
    destructor Destroy; override;
  end;

  EDLVehicleDBError = Exception;
  
  TDALVDCenter = class(TDzPersistent, IVehicleDatabase)
  private
    Connections: TVDConnection;
    ConnCount: Integer;
    ConnLock: TSynchroObject;
    Semaphore: THandle;
    fPort: Word;
    fHost: AnsiString;
    function GetConnection: TVDConnection;
    procedure ReleaseConnection(conn: TVDConnection);
    procedure DoRequest(Connection: TVDConnection; command: LongInt;
      request: TDLCustomDataObject; response: TCustomResponse;
      out Output: TFuncCallResult);
    procedure GetVehicleData(Car_InfoType: LongInt; Car_Source: ShortInt;
      SuoShuYongHu: LongInt; State: ShortInt;
      const CityCode, ToCityCode: array of LongInt;
      const SiJiXingMing, ChePaiHaoMa, SuiCheShouJi, CheZhang,
      DunWei, RongJi, CheKuan, CheGao, BeiZhu: AnsiString;
      IndexFrom, GetCount: LongInt; resp: TCustomResponse;
      out Output: TFuncCallResult);
    procedure _GetShareVehicle(ObjectType: TLBSObjectType; Filter: TShareVehicleFilter;
      PageIndex, PageSize: Integer; List: TDzPersistentList; 
      Param: Pointer; Callback: TSimpleCallback);
  public
    constructor Create; override;
    destructor Destroy; override;
    procedure CleanupConnections;

    {$region 'IVehicleDatabase'}
    procedure GetPriVehicle(UserId, PageSize, PageIndex: Integer;
      Filter: TPriVehicleFilter; List: TDzPersistentList;
      Param: Pointer; Callback: TSimpleCallback);

    procedure GetShareVehicle(Filter: TShareVehicleFilter;
      PageIndex, PageSize: Integer; List: TDzPersistentList; 
      Param: Pointer; Callback: TSimpleCallback);
  
    procedure GetWebShareVehicle(Filter: TWebShareVehicleFilter;
      PageIndex, PageSize: Integer; List: TDzPersistentList; 
      Param: Pointer; Callback: TSimpleCallback);
      
    procedure RemovePriVehicle(List: TDzPersistentList;
      Param: Pointer; Callback: TSimpleCallback);

    procedure AddPriVehicle(Vehicle: TVehicle; Param: Pointer;
      Callback: TSimpleCallback);

    procedure ModifyPriVehicle(Vehicle: TVehicle; Param: Pointer;
      Callback: TSimpleCallback);

    procedure RemoveLocPerson(List: TDzPersistentList; Param: Pointer;
      Callback: TSimpleCallback);
    
    procedure AddLocPerson(Person: TLocPerson; Param: Pointer;
      Callback: TSimpleCallback);

    procedure ModifyLocPerson(Person: TLocPerson; Param: Pointer;
      Callback: TSimpleCallback);
    
    procedure GetLocPerson(UserID, PageIndex, PageSize: Integer;
      Filter: TLocPersonFilter; List: TDzPersistentList;
      Param: Pointer; Callback: TSimpleCallback);
      
    procedure SaveLocateResult(const Phone, Longitude, Latitude: AnsiString;
      const Address, CityName: WideString; CityCode, UserID, ObjectID, Consume: Integer;
      Method: TLbmpLocType; Param: Pointer; Callback: TSimpleCallback);
      
    procedure SetAutoLocTime(UserID, Hour: Integer;
      Param: Pointer; Callback: TSimpleCallback);
    
    procedure GetLocTrace(ID: Integer; Tracing: TLocTrace;
      Param: Pointer; Callback: TSimpleCallback);
    
    procedure AddLocTrace(Tracing: TLocTrace; Param: Pointer; Callback: TSimpleCallback);
    
    procedure RemoveLocTrace(ID: Integer; Param: Pointer; Callback: TSimpleCallback);

    procedure ModifyLocTrace(Tracing: TLocTrace; Param: Pointer;
      Callback: TSimpleCallback);
    
    procedure ModifyLBMPState(const Phone: AnsiString; State: Integer;
      Param: Pointer; Callback: TSimpleCallback);
    {$endregion}
    
  published
    property Host: AnsiString read fHost write fHost;
    property Port: Word read fPort write fPort;
  end;

implementation

type
  TDynIntArray = array of Integer;
  
procedure SplitCityCodes(const str: AnsiString; var arr: TDynIntArray);
var
  i, num: Integer;
begin
  num := 0;
  SetLength(arr, 0);
  for i := 1 to Length(str) do
  begin
    if str[i] in ['0'..'9'] then
      num := 10 * num + Byte(str[i]) and $0f
    else begin
      SetLength(arr, Length(arr) + 1);
      arr[High(arr)] := num;
      num := 0;
    end;
  end;
  if num <> 0 then
  begin
    SetLength(arr, Length(arr) + 1);
    arr[High(arr)] := num;
  end;
end;

procedure SetVDItemCityCodes(VDItem: TVehicleItem; const Str: string);
var
  i, num: Integer;
begin
  VDItem.WalkUpTo.Clear;
  num := 0;
  for i := 1 to Length(Str) do
  begin
    if Str[i] in ['0'..'9'] then
      num := 10 * num + Byte(Str[i]) and $0f
    else begin
      with TVehicleWalkUpToItem(VDItem.WalkUpTo.Add) do
      begin
        ToCityCode := num;
        CityName := '';
      end;
      num := 0;
    end;
  end;
  if num <> 0 then
  with TVehicleWalkUpToItem(VDItem.WalkUpTo.Add) do
  begin
    ToCityCode := num;
    CityName := '';
  end;
end;

procedure AssignVDVehicleItem(vehicle: TVehicle; VDItem: TWebVehicleItem);
begin
  vehicle.GUID := VDItem.CheLiangBianHao;
  VDItem.ChePaiHaoMa := vehicle.Name;
  VDItem.SuiCheShouJi := vehicle.Phone;
  VDItem.SiJiXingMing := vehicle.SiJiXingMing;
  
  VDItem.ZhuCeFou := vehicle.StateCode;
  //VDItem.CityCode := vehicle.CityID;
  VDItem.CheLiangWeiZhi := vehicle.Position;
  //VDItem.WeiZhiMiaoShu := vehicle.Address;
  VDItem.DingWeiShiJian := vehicle.LastLocateTime;
  
  //VDItem.Car_AddTime := vehicle.Car_AddTime;
end;

procedure AssignVehicle(vehicle: TVehicle; VDItem: TVehicleItem);
begin
  VDItem.SuoShuYongHu := vehicle.SuoShuYongHu;
  VDItem.ChePaiHaoMa := vehicle.Name;
  VDItem.CheXing := vehicle.CheXing;
  VDItem.CheZhang := vehicle.CheZhang;
  VDItem.CheKuan := vehicle.CheKuan;
  VDItem.CheGao := vehicle.CheGao;
  VDItem.DunWei := vehicle.DunWei;
  VDItem.RongJi := IntToStr(vehicle.RongJi);
  VDItem.FaDongJiHao := vehicle.FaDongJiHao;
  VDItem.CheJiaHaoMa := vehicle.CheJiaHaoMa;
  VDItem.BaoXianKaHao := vehicle.BaoXianKaHao;
  VDItem.GuaKaoDanWei := vehicle.GuaKaoDanWei;
  VDItem.YunYingZhengShu := vehicle.YunYingZhengShu;
  VDItem.HuoYunZhuangTai := vehicle.HuoYunZhuangTai;
  VDItem.QiWangLiuXiang := vehicle.QiWangLiuXiang;
  VDItem.CheZhuXingMing := vehicle.CheZhuXingMing;
  VDItem.CheZhuShouJi := vehicle.CheZhuShouJi;
  VDItem.CheZhuShenFenZhengHao := vehicle.CheZhuShenFenZhengHao;
  VDItem.CheZhuQiTaDianHua := vehicle.CheZhuQiTaDianHua;
  VDItem.CheZhuXingBie := vehicle.CheZhuXingBie;
  VDItem.CheZhuDianHuaHaoMa := vehicle.CheZhuDianHuaHaoMa;
  VDItem.CheZhuJiaTingZhuZhi := vehicle.CheZhuJiaTingZhuZhi;
  VDItem.SiJiXingMing := vehicle.SiJiXingMing;
  VDItem.SuiCheShouJi := vehicle.Phone;
  VDItem.SiJiShenFenZhengHao := vehicle.SiJiShenFenZhengHao;
  VDItem.SiJiXingBie := vehicle.SiJiXingBie;
  VDItem.JiaShiZhiZhao := vehicle.JiaShiZhiZhao;
  VDItem.SiJiJiaTingDianHua := vehicle.SiJiJiaTingDianHua;
  VDItem.SiJiQiTaDianHua := vehicle.SiJiQiTaDianHua;
  VDItem.SiJiJiaTingZhuZhi := vehicle.SiJiJiaTingZhuZhi;
  VDItem.BeiZhu := vehicle.BeiZhu;

  VDItem.ZhuCeFou := vehicle.StateCode;
  VDItem.CityCode := vehicle.CityID;
  VDItem.CheLiangWeiZhi := vehicle.Position;
  VDItem.DingWeiShiJian := vehicle.LastLocateTime;
  VDItem.WeiZhiMiaoShu := vehicle.Address;
  
  SetVDItemCityCodes(VDItem, vehicle.ToCityCode);
end;

procedure AssignVDItem(vehicle: TVehicle; VDItem: TVehicleItem);
begin
  vehicle.GUID := VDItem.CheLiangBianHao;
  vehicle.SuoShuYongHu := VDItem.SuoShuYongHu;
  vehicle.Name := VDItem.ChePaiHaoMa;
  vehicle.CheXing := VDItem.CheXing;
  vehicle.CheZhang := VDItem.CheZhang;
  vehicle.CheKuan := VDItem.CheKuan;
  vehicle.CheGao := VDItem.CheGao;
  vehicle.DunWei := VDItem.DunWei;
  vehicle.RongJi := StrToIntDef(VDItem.RongJi, 0);
  vehicle.FaDongJiHao := VDItem.FaDongJiHao;
  vehicle.CheJiaHaoMa := VDItem.CheJiaHaoMa;
  vehicle.BaoXianKaHao := VDItem.BaoXianKaHao;
  vehicle.GuaKaoDanWei := VDItem.GuaKaoDanWei;
  vehicle.YunYingZhengShu := VDItem.YunYingZhengShu;
  vehicle.HuoYunZhuangTai := VDItem.HuoYunZhuangTai;
  vehicle.QiWangLiuXiang := VDItem.QiWangLiuXiang;
  vehicle.CheZhuXingMing := VDItem.CheZhuXingMing;
  vehicle.CheZhuShouJi := VDItem.CheZhuShouJi;
  vehicle.CheZhuShenFenZhengHao := VDItem.CheZhuShenFenZhengHao;
  vehicle.CheZhuQiTaDianHua := VDItem.CheZhuQiTaDianHua;
  vehicle.CheZhuXingBie := VDItem.CheZhuXingBie;
  vehicle.CheZhuDianHuaHaoMa := VDItem.CheZhuDianHuaHaoMa;
  vehicle.CheZhuJiaTingZhuZhi := VDItem.CheZhuJiaTingZhuZhi;
  vehicle.SiJiXingMing := VDItem.SiJiXingMing;
  vehicle.Phone := VDItem.SuiCheShouJi;
  vehicle.SiJiShenFenZhengHao := VDItem.SiJiShenFenZhengHao;
  vehicle.SiJiXingBie := VDItem.SiJiXingBie;
  vehicle.JiaShiZhiZhao := VDItem.JiaShiZhiZhao;
  vehicle.SiJiJiaTingDianHua := VDItem.SiJiJiaTingDianHua;
  vehicle.SiJiQiTaDianHua := VDItem.SiJiQiTaDianHua;
  vehicle.SiJiJiaTingZhuZhi := VDItem.SiJiJiaTingZhuZhi;
  vehicle.StateCode := VDItem.ZhuCeFou;
  vehicle.BeiZhu := VDItem.BeiZhu;
  vehicle.CityID := VDItem.CityCode;
  vehicle.Position := VDItem.CheLiangWeiZhi;
  vehicle.Address := VDItem.WeiZhiMiaoShu;
  vehicle.LastLocateTime := VDItem.DingWeiShiJian;
end;

procedure VehicleItemToLocPerson(Person: TLocPerson; VDItem: TVehicleItem);
begin
  Person.UserID := VDItem.SuoShuYongHu;
  Person.Remark := VDItem.BeiZhu;
  Person.Sex := VDItem.SiJiXingBie;
  Person.GUID := VDItem.CheLiangBianHao;
  Person.Name := VDItem.SiJiXingMing;
  Person.Phone := VDItem.SuiCheShouJi;

  Person.StateCode := VDItem.ZhuCeFou;
  Person.CityID := VDItem.CityCode;
  Person.Position := VDItem.CheLiangWeiZhi;
  Person.Address := VDItem.WeiZhiMiaoShu;
  Person.LastLocateTime := VDItem.DingWeiShiJian;
end;

procedure LocPersonToVehicleItem(
  Person: TLocPerson; VDItem: TVehicleItem);
begin
  VDItem.SuoShuYongHu := Person.UserID;
  VDItem.BeiZhu := Person.Remark;
  VDItem.SiJiXingBie := Person.Sex;
  VDItem.CheLiangBianHao := Person.GUID;
  VDItem.SiJiXingMing := Person.Name;
  VDItem.SuiCheShouJi := Person.Phone;

  VDItem.ZhuCeFou := Person.StateCode;
  VDItem.CityCode := Person.CityID;
  VDItem.CheLiangWeiZhi := Person.Position;
  VDItem.WeiZhiMiaoShu := Person.Address;
  VDItem.DingWeiShiJian := Person.LastLocateTime;
end;

function SystemBusy(out FuncResult: TFuncCallResult): Boolean; inline;
begin
  FuncResult.ErrCode := CXT_E_SYSTEM_BUSY;
  FuncResult.ErrMsg := SSystemBusy;
  Result := False;
end;

{ TVDConnection }

constructor TVDConnection.Create;
begin
  Socket := TDzClientSocket.Create;
end;

destructor TVDConnection.Destroy;
begin
  Socket.Free;
  inherited;
end;

{ TDALVDCenter }

procedure TDALVDCenter.AddLocPerson(Person: TLocPerson;
  Param: Pointer; Callback: TSimpleCallback);
var
  conn: TVDConnection;
  req: TAddVehicleRequest;
  resp: TAddVehicleResponse;
  Output: TFuncCallResult;
begin
  conn := GetConnection;
  Output.AsInteger := 0;
  resp := nil;
  if conn = nil then
  begin
    SystemBusy(Output);
    Callback(Output, Param);
    Exit;
  end;
  try
    req := TAddVehicleRequest.Create;
    try
      LocPersonToVehicleItem(Person, req);
      resp := TAddVehicleResponse.Create;
      req.Car_InfoType := 2;
      req.Car_Source := 0;
      req.AutoLocTime := 0;
      req.Car_IsGift := 0;
      req.ZhuCeFou := -1;
      DoRequest(conn, gcCmdAddVehicle, req, resp, Output);
      if Output.ErrCode = 0 then
      begin
        Inc(Output.AsInteger);
        Person.GUID := resp.CheLiangBianHao;
      end;
      Callback(Output, Param);
    finally
      req.Free;
      if resp <> nil then resp.Free;
    end;
  finally
    ReleaseConnection(conn);
  end;
end;

procedure TDALVDCenter.AddLocTrace(Tracing: TLocTrace;
  Param: Pointer; Callback: TSimpleCallback);
var
  conn: TVDConnection;
  Output: TFuncCallResult;
begin
  conn := Self.GetConnection;
  if conn = nil then
  begin
    SystemBusy(Output);
    Exit;
  end;
  try
    Output.ErrCode := CXT_E_SUCCESS;
    Output.ErrMsg := '';
  finally
    Self.ReleaseConnection(conn);
  end;
end;

procedure TDALVDCenter.AddPriVehicle(Vehicle: TVehicle;
  Param: Pointer; Callback: TSimpleCallback);
var
  conn: TVDConnection;
  req: TAddVehicleRequest;
  resp: TAddVehicleResponse;
  Output: TFuncCallResult;
begin
  conn := GetConnection;
  resp := nil;
  Output.AsInteger := 0;
  if conn = nil then
  begin
    SystemBusy(Output);
    Callback(Output, Param);
    Exit;
  end;
  try
    req := TAddVehicleRequest.Create;
    try
      AssignVehicle(vehicle, req);
      resp := TAddVehicleResponse.Create;
      req.Car_InfoType := 1;
      req.Car_Source := 1;
      req.AutoLocTime := 0;
      req.Car_IsGift := 0;
      req.ZhuCeFou := -1;
      req.BeiZhu := vehicle.BeiZhu;
      DoRequest(conn, gcCmdAddVehicle, req, resp, Output);
      if Output.ErrCode = 0 then Vehicle.GUID := resp.CheLiangBianHao;
      Callback(Output, Param);
    finally
      req.Free;
      if resp <> nil then resp.Free;
    end;
  finally
    ReleaseConnection(conn);
  end;
end;

procedure TDALVDCenter.CleanupConnections;
var
  conn: TVDConnection;
begin
  ConnLock.Acquire;
  try
    while Connections <> nil do
    begin
      conn := Connections;
      Connections := Connections.Next;
      conn.Free;
    end;
  finally
    ConnLock.Release;
  end;
end;

constructor TDALVDCenter.Create;
begin
  inherited;
  ConnLock := TCriticalSection.Create;
  Semaphore := Windows.CreateSemaphore(nil, 0, MaxInt, nil);
end;

destructor TDALVDCenter.Destroy;
begin
  CleanupConnections;
  Windows.CloseHandle(Semaphore);
  ConnLock.Free;
  inherited;
end;

procedure TDALVDCenter.DoRequest(Connection: TVDConnection; command: Integer;
  request: TDLCustomDataObject; response: TCustomResponse;
  out Output: TFuncCallResult);
var
  ms: TMemoryStream;
  reqh: TReqHead;
  resph: TRespHead;
begin
  ms := TMemoryStream.Create;
  try
    if not Connection.Socket.Connected then
    begin
      Connection.Socket.Connect(Self.Host, Self.Port);
      //'60.172.42.42' 544
    end;

    request.SaveToStream(ms);
    reqh.Flag := gcFlag;
    reqh.Cmd := command;
    reqh.DatLen := ms.Size;
    Connection.Socket.Write(reqh, SizeOf(reqh));
    while True do
    try
      Connection.Socket.Write(ms.Memory^, ms.Size);
      Connection.Socket.Read(resph, SizeOf(resph), nil, MSG_WAITALL);
      if resph.DatLen > 0 then
        begin
          ms.Size := resph.DatLen;
          Writeln('vehicle data ', resph.DatLen, ' bytes');
          Connection.Socket.Read(ms.Memory^, resph.DatLen, nil, MSG_WAITALL);
          ms.Position := 0;
          response.LoadFromStream(ms);
          if response.Success then
          begin
            Output.ErrCode := CXT_E_SUCCESS;
            Output.ErrMsg := '';
          end
          else begin
            Output.ErrCode := CXT_E_DBENGINE;
            Output.ErrMsg := response.ErrMsg;
          end;
        end
      else begin
        Output.ErrCode := CXT_E_DBENGINE;
        Output.ErrMsg := SUnknownError;
      end;
      Break;
    except
      on E: EDzConnectionClosed do
      begin
        Connection.Socket.Close;
        Connection.Socket.Connect(Self.Host, Self.Port);
      end
      else raise;
    end;
  finally
    ms.Destroy;
  end;
end;

function TDALVDCenter.GetConnection: TVDConnection;
begin
  ConnLock.Acquire;
  try
    Result := Connections;
    if Result <> nil then
    begin
      Connections := Result.Next;
      Exit;
    end;
    if ConnCount < AppConfig.DBConnectionPoolSize then
    begin
      InterlockedIncrement(ConnCount);
      Result := TVDConnection.Create;
      Result.Next := nil;
      Exit;
    end;
    ConnLock.Release;
    WaitForSingleObject(Semaphore, INFINITE);
    ConnLock.Acquire;
    Result := Connections;
    if Result <> nil then Connections := Result.Next;    
  finally
    ConnLock.Release;  
  end;
end;

procedure TDALVDCenter.GetLocPerson(UserID, PageIndex, PageSize: Integer;
  Filter: TLocPersonFilter; List: TDzPersistentList;
  Param: Pointer; Callback: TSimpleCallback);
var
  resp: TGetVehicleResponse;
  CityCodes, ToCityCodes: TDynIntArray;
  j: Integer;
  Output: TFuncCallResult;
begin
  SplitCityCodes(Filter.InCityCode, CityCodes);
  SplitCityCodes(Filter.ToCityCode, ToCityCodes);
  resp := TGetVehicleResponse.Create;
  try
    GetVehicleData(2, 0, UserId, Ord(Filter.Locatable) - 1,
      CityCodes, ToCityCodes, Filter.PersonName, '',
      Filter.Phone, '', '', '', '', '', '',
      PageIndex * PageSize, PageSize, resp, Output);
    if Output.ErrCode = 0 then
    begin
      Output.AsInteger := resp.MatchCount;
      for j := 0 to resp.Items.Count - 1 do
        VehicleItemToLocPerson(TLocPerson(list.Add),
          TVehicleItem(resp.Items.Items[j]));
    end;
    Callback(Output, Param);
  finally
    resp.Free;
  end;
end;

procedure TDALVDCenter.GetLocTrace(ID: Integer; Tracing: TLocTrace;
  Param: Pointer; Callback: TSimpleCallback);
var
  Output: TFuncCallResult;
begin
  Output.ErrCode := CXT_E_SUCCESS;
  Output.ErrMsg := '';
  Callback(Output, Param);
end;

procedure TDALVDCenter.GetPriVehicle(UserId, PageSize, PageIndex: Integer;
  Filter: TPriVehicleFilter; List: TDzPersistentList; 
  Param: Pointer; Callback: TSimpleCallback);
var
  resp: TGetVehicleResponse;
  CityCodes, ToCityCodes: TDynIntArray;
  i: Integer;
  Output: TFuncCallResult;
begin
  SplitCityCodes(Filter.InCityCode, CityCodes);
  SplitCityCodes(Filter.ToCityCode, ToCityCodes);
  resp := TGetVehicleResponse.Create;
  try
    GetVehicleData(1, 0, UserId, Ord(Filter.Locatable) - 1,
      CityCodes, ToCityCodes, Filter.SiJiXingMing, Filter.ChePaiHaoMa,
      Filter.Phone, Filter.CheZhang, Filter.DunWei, Filter.RongJi,
      Filter.CheKuan, Filter.CheGao, Filter.BeiZhu,
      PageIndex * PageSize, PageSize, resp, Output);
    if Output.ErrCode = 0 then
    begin
      Output.AsInteger := resp.MatchCount;
      for i := 0 to resp.Items.Count - 1 do
        AssignVDItem(TVehicle(list.Add), TVehicleItem(resp.Items.Items[i]));
    end;
    Callback(Output, Param);
  finally
    resp.Free;
  end;
end;

procedure TDALVDCenter._GetShareVehicle(ObjectType: TLBSObjectType;
  Filter: TShareVehicleFilter; PageIndex, PageSize: Integer;
  List: TDzPersistentList; Param: Pointer;
  Callback: TSimpleCallback);
var
  resp: TGetVehicleResponse;
  CityCodes, ToCityCodes: TDynIntArray;
  i: Integer;
  Output: TFuncCallResult;
begin
  SplitCityCodes(Filter.InCityCode, CityCodes);
  SplitCityCodes(Filter.ToCityCode, ToCityCodes);
  resp := TGetVehicleResponse.Create;
  try
    GetVehicleData(1, Ord(ObjectType), 0, Ord(Filter.Locatable) - 1,
      CityCodes, ToCityCodes, '', '', '', Filter.CheZhang, Filter.DunWei,
      Filter.RongJi, Filter.CheKuan, Filter.CheGao, Filter.BeiZhu,
      PageIndex * PageSize, PageSize, resp, Output);
    if Output.ErrCode = 0 then
    begin
      Output.AsInteger := resp.MatchCount;
      for i := 0 to resp.Items.Count - 1 do
        AssignVDItem(TVehicle(list.Add), TVehicleItem(resp.Items.Items[i]));
    end;
    Callback(Output, Param);
  finally
    resp.Free;
  end;
end;

procedure TDALVDCenter.GetShareVehicle(Filter: TShareVehicleFilter; 
  PageIndex, PageSize: Integer; List: TDzPersistentList; 
  Param: Pointer; Callback: TSimpleCallback);
begin
  _GetShareVehicle(otShare, Filter, PageIndex, PageSize, List, Param, Callback); 
end;
  
procedure TDALVDCenter.GetWebShareVehicle(Filter: TWebShareVehicleFilter; 
  PageIndex, PageSize: Integer; List: TDzPersistentList; 
  Param: Pointer; Callback: TSimpleCallback);
begin 
  _GetShareVehicle(otShare, Filter, PageIndex, PageSize, List, Param, Callback);
end;

procedure TDALVDCenter.ModifyLocPerson(Person: TLocPerson;
  Param: Pointer; Callback: TSimpleCallback);
var
  conn: TVDConnection;
  req: TUpdateVehicleRequest;
  resp: TUpdateVehicleResponse;
  Output: TFuncCallResult;
begin
  conn := GetConnection;
  if conn = nil then
  begin
    SystemBusy(Output);
    Callback(Output, Param);
    Exit;
  end;
  try
    req := TUpdateVehicleRequest.Create;
    try
      LocPersonToVehicleItem(Person, req);
      req.Car_InfoType := 2;
      req.Car_Source := 0;
      resp := TUpdateVehicleResponse.Create;
      try
        DoRequest(conn, gcCmdUpdateVehicle, req, resp, Output);
        if Output.ErrCode = 0 then Output.AsInteger := 1;
        Callback(Output, Param);
      finally
        resp.Free;
      end;
    finally
      req.Free;
    end;
  finally
    ReleaseConnection(conn);
  end;
end;

procedure TDALVDCenter.ModifyLBMPState(const Phone: AnsiString; State: Integer;
  Param: Pointer; Callback: TSimpleCallback);
var
  conn: TVDConnection;
  request: TUpdateStateRequest;
  response: TUpdateStateResponse;
  Output: TFuncCallResult;
begin
  conn := Self.GetConnection;
  if conn = nil then
  begin
    SystemBusy(Output);
    Callback(Output, Param);
    Exit;
  end;
  request := TUpdateStateRequest.Create;
  request.SuiCheShouJi := Phone;
  request.ZhuCeFou := State;
  response := TUpdateStateResponse.Create;
  try
    DoRequest(conn, gcCmdUpdateState, request, response, Output);
    Callback(Output, Param);
  finally
    request.Free;
    response.Free;
    Self.ReleaseConnection(conn);
  end;
end;

procedure TDALVDCenter.ModifyLocTrace(Tracing: TLocTrace; 
	Param: Pointer; Callback: TSimpleCallback);
var
  conn: TVDConnection;
  Output: TFuncCallResult;
begin
  conn := Self.GetConnection;
  if conn = nil then
  begin
    SystemBusy(Output);
    Callback(Output, Param);
    Exit;
  end;
  try
    Output.ErrCode := CXT_E_SUCCESS;
    Output.ErrMsg := '';
    Callback(Output, Param);
  finally
    Self.ReleaseConnection(conn);
  end;
end;

procedure TDALVDCenter.ModifyPriVehicle(Vehicle: TVehicle; 
	Param: Pointer; Callback: TSimpleCallback);
var
  conn: TVDConnection;
  req: TUpdateVehicleRequest;
  resp: TUpdateVehicleResponse;
  Output: TFuncCallResult;
begin
  conn := GetConnection;
  if conn = nil then
  begin
    SystemBusy(Output);
    Callback(Output, Param);
    Exit;
  end;
  try
    req := TUpdateVehicleRequest.Create;
    try
      AssignVehicle(vehicle, req);
      req.Car_InfoType := 1;
      req.Car_Source := 1;
      req.CheLiangBianHao := vehicle.GUID;
      resp := TUpdateVehicleResponse.Create;
      try
        DoRequest(conn, gcCmdUpdateVehicle, req, resp, Output);
        if Output.ErrCode = 0 then Output.AsInteger := 1;
        Callback(Output, Param);
      finally
        resp.Free;
      end;
    finally
      req.Free;
    end;
  finally
    ReleaseConnection(conn);
  end;
end;

procedure TDALVDCenter.ReleaseConnection(conn: TVDConnection);
begin
  ConnLock.Acquire;
  try
    conn.Next := Connections;
    Connections := conn;
  finally
    ConnLock.Release;
  end;
  Windows.ReleaseSemaphore(Semaphore, 1, nil);
end;

procedure TDALVDCenter.RemoveLocPerson(List: TDzPersistentList;
  Param: Pointer; Callback: TSimpleCallback);
begin
  RemovePriVehicle(List, Param, Callback);
end;

procedure TDALVDCenter.RemoveLocTrace(ID: Integer;
	Param: Pointer; Callback: TSimpleCallback);
var
  conn: TVDConnection;
  Output: TFuncCallResult;
begin
  conn := Self.GetConnection;
  if conn = nil then
  begin
    SystemBusy(Output);
    Callback(Output, Param);
    Exit;
  end;
  try
    Output.ErrCode := CXT_E_SUCCESS;
    Output.ErrMsg := '';
    Callback(Output, Param);
  finally
    Self.ReleaseConnection(conn);
  end;
end;

procedure TDALVDCenter.RemovePriVehicle(List: TDzPersistentList;
  Param: Pointer; Callback: TSimpleCallback);
var
  conn: TVDConnection;
  req: TDeleteVehicleListRequest;
  resp: TDeleteVehicleListResponse;
  i: Integer;
  Output: TFuncCallResult;
begin
  conn := Self.GetConnection;
  if conn = nil then
  begin
    SystemBusy(Output);
	  Callback(Output, Param);
    Exit;
  end;
  try
    req := TDeleteVehicleListRequest.Create;
    for i := 0 to List.Count - 1 do
      req.CheLiangBianHao.Add(TObjectKey(List[i]).ObjectID);
    req.SaveForReUse := True;
    resp := TDeleteVehicleListResponse.Create;
    try
      DoRequest(conn, gcCmdDelVehicleList, req, resp, Output);
      if Output.ErrCode = 0 then Output.AsInteger := resp.SuccessCount;
      Callback(Output, Param);
    finally
      req.Free;
      resp.Free;
    end;
  finally
    Self.ReleaseConnection(conn);
  end;
end;

procedure TDALVDCenter.SaveLocateResult(const Phone, Longitude, Latitude: AnsiString;
  const Address, CityName: WideString; CityCode, UserID, ObjectID, Consume: Integer;
  Method: TLbmpLocType; Param: Pointer; Callback: TSimpleCallback);
var
  conn: TVDConnection;
  req: TUpdateLocationRequest;
  resp: TUpdateLocationResponse;
  Output: TFuncCallResult;
begin
  conn := Self.GetConnection;
  if conn = nil then
  begin
    SystemBusy(Output);
    Callback(Output, Param);
    Exit;
  end;
  try
    req := TUpdateLocationRequest.Create;
    req.CheLiangBianHao := ObjectID;
    req.DingWeiShiJian := Now;
    req.JingDu := Longitude;
    req.WeiDu := Latitude;
    req.CheLiangWeiZhi := CityName;
    req.WeiZhiMiaoShu := Address;
    req.CityCode := CityCode;
    req.ZhuCeFou := 3;
    resp := TUpdateLocationResponse.Create;
    try
      DoRequest(conn, gcCmdUpdateLocation, req, resp, Output);
      Callback(Output, Param);
    finally
      req.Free;
      resp.Free;  
    end;
  finally
    Self.ReleaseConnection(conn);
  end;
end;

procedure TDALVDCenter.SetAutoLocTime(UserID, Hour: Integer;
  Param: Pointer; Callback: TSimpleCallback);
var
  Output: TFuncCallResult;
begin
  Output.ErrCode := CXT_E_SUCCESS;
  Output.ErrMsg := '';
  Callback(Output, Param);
end;

procedure TDALVDCenter.GetVehicleData(Car_InfoType: Integer;
  Car_Source: ShortInt; SuoShuYongHu: Integer; State: ShortInt;
  const CityCode, ToCityCode: array of Integer; const SiJiXingMing,
  ChePaiHaoMa, SuiCheShouJi, CheZhang, DunWei, RongJi, CheKuan,
  CheGao, BeiZhu: AnsiString; IndexFrom, GetCount: Integer;
  resp: TCustomResponse; out Output: TFuncCallResult);
var  
  req: TGetVehicleRequest;
  conn: TVDConnection;
begin
  conn := Self.GetConnection;
  if conn = nil then
  begin
    SystemBusy(Output);
    Exit;
  end;
  try
    req := TGetVehicleRequest.Create;
    try
      req.SetParam(Car_InfoType, Car_Source, SuoShuYongHu, State,
        CityCode, ToCityCode, SiJiXingMing, ChePaiHaoMa, SuiCheShouJi,
        CheZhang, DunWei, RongJi, CheKuan, CheGao, BeiZhu,
        IndexFrom, GetCount);
      DoRequest(conn, gcCmdGetVehicle, req, resp, Output);
    finally
      req.Free;
    end;
  finally
    Self.ReleaseConnection(conn);
  end;
end;

end.
